package com.yungee.logic;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.tobato.fastdfs.domain.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.fdfs.StorePath;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import com.yungee.base.entity.FileUploadRecord;
import com.yungee.base.service.impl.FileUploadRecordServiceImpl;
import com.yungee.model.PageData;
import com.yungee.util.FileUtil;
import com.yungee.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class UploadFileLogic {

    @Autowired
    protected FastFileStorageClient storageClient;

    @Autowired
    private FdfsWebServer fdfsWebServer;

    @Autowired
    private FileUploadRecordServiceImpl fileUploadRecordService;

    /**
     * 上传图片
     * @param file
     * @return
     */
    public String uploadFile(MultipartFile file) {
        String fileUrl = null;
        String fullPath = null;
        String originFileName = file.getOriginalFilename();
        String extName = FileUtil.getFileExtension(file);
        long size = file.getSize();
        String contentType = file.getContentType();
        log.info("上传文件到fdfs开始:originFileName={},size={},contentType={},extName={}",originFileName,size,contentType,extName);
        //计算md5
        String md5Hex = FileUtil.md5Hex(file);
        //查询是否存在相同文件
        FileUploadRecord fileUploadRecord = checkFileUploadRecordExist(md5Hex);
        if (Objects.nonNull(fileUploadRecord)){
            log.info("文件已存在,md5={},文件名={}",md5Hex,originFileName);
            fileUrl = fdfsWebServer.getWebServerUrl() + "/" + fileUploadRecord.getUrl();
            return fileUrl;
        }
        log.info("文件不存在，准备上传,md5={},文件名={}",md5Hex,originFileName);
        try {
            StorePath storePath = null;
            String thumbImage = null;
            if (file.getContentType().startsWith("image/")){
                log.info("上传图片文件,md5={},文件名={}",md5Hex,originFileName);
                storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(),file.getSize(), extName, null);
                fullPath = storePath.getFullPath();
                int index = fullPath.lastIndexOf(".");
                if (index!=-1){
                    thumbImage = fullPath.substring(0, index)+"_150x150"+fullPath.substring(index);
                }
            }else {
                log.info("上传其他文件,md5={},文件名={}",md5Hex,originFileName);
                storePath = storageClient.uploadFile(file.getInputStream(),file.getSize(), extName, null);
                fullPath = storePath.getFullPath();
            }
            insertFileUploadRecord(originFileName,fullPath,md5Hex,size,contentType,thumbImage);
            fileUrl = fdfsWebServer.getWebServerUrl() + "/" + storePath.getFullPath();
            log.info("上传文件到fdfs结束,fullPath={},地址={}",fullPath,fileUrl);
            return fileUrl;
        } catch (IOException e) {
            log.error("上传文件到fdfs失败",e);
        }
        return fileUrl;
    }

    /**
     * 检查文件是否已经上传
     * @param md5Hex
     * @return
     */
    private FileUploadRecord checkFileUploadRecordExist(String md5Hex) {
        List<FileUploadRecord> fileUploadRecordList = fileUploadRecordService.getByMd5(md5Hex);
        return CollectionUtils.isNotEmpty(fileUploadRecordList)?fileUploadRecordList.get(0):null;
    }

    /**
     * 插入文件上传记录
     *
     * @param originFileName
     * @param fullPath
     * @param md5Hex
     * @param size
     * @param fileType
     */
    private void insertFileUploadRecord(String originFileName, String fullPath, String md5Hex, long size, String fileType,String thumbImage) {
        FileUploadRecord fileUploadRecord = new FileUploadRecord();
        fileUploadRecord.setUrl(fullPath);
        fileUploadRecord.setOriginFileName(originFileName);
        fileUploadRecord.setCreateTime(new Date());
        fileUploadRecord.setMd5(md5Hex);
        fileUploadRecord.setFileSize(size);
        fileUploadRecord.setFileType(fileType);
        fileUploadRecord.setThumbImage(thumbImage);
        fileUploadRecordService.save(fileUploadRecord);
    }

    /**
     * 分页查询
     *
     * @param page
     * @param size
     * @param fileType
     * @return
     */
    public PageData filePage(int page, int size, String fileType) {
        Page<FileUploadRecord> pageQuery = new Page<>(page,size);
        QueryWrapper<FileUploadRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("status", 1);
        if (StringUtils.isNotEmpty(fileType)){
            queryWrapper.eq("file_type", fileType);
        }
        queryWrapper.orderByDesc("id");
        Page<FileUploadRecord> uploadRecordPage = fileUploadRecordService.page(pageQuery, queryWrapper);
        long total = pageQuery.getTotal();
        List<FileUploadRecord> records = uploadRecordPage.getRecords();
        if (CollectionUtils.isNotEmpty(records)){
            for (FileUploadRecord record : records) {
                record.setUrl(fdfsWebServer.getWebServerUrl() + "/" + record.getUrl());
                if (StringUtils.isNotEmpty(record.getThumbImage())){
                    record.setThumbImage(fdfsWebServer.getWebServerUrl() + "/" + record.getThumbImage());
                }
            }
        }
        PageData pageData = new PageData(total,records);
        return pageData;
    }

    /**
     * 删除文件
     * @param id
     * @return
     */
    public boolean deleteFile(Long id) {
        FileUploadRecord fileUploadRecord = fileUploadRecordService.getById(id);
        if (Objects.isNull(fileUploadRecord)){
            return false;
        }
        storageClient.deleteFile(fileUploadRecord.getUrl());
        fileUploadRecord.setStatus(0);
        fileUploadRecordService.updateById(fileUploadRecord);
        return true;
    }
}
